#ifdef __GNUG__
#pragma implementation
#endif

#include "File.h"
#include "String.h"
#include "ET_stdio.h"
#include "ET_stdlib.h"
#include "ET_errno.h"

extern "C" {
	int open(const char*, int);
	int creat(const char*, int);
	int close(int);
	int read(int, char*, int);
	int write(int, const char*, int);
	long lseek(int, long, int);
	int unlink(const char*);
	int link(const char*, const char*);

	int unix_nonblock(int fd);
};

static char *fdnames[256];

void File::Cleanup()
{
	for (int i= 0; i < 256; i++) {
		if (fdnames[i]) {
			fprintf(stderr, "file \"%s\" (%d) not closed\n", fdnames[i], i);
			delete fdnames[i];
			fdnames[i]= 0;
		}
	}
}

int File::AddFdName(int fd, const char *name, const char *msg)
{
	if (fd >= 0 && fd < 256) {
		if (fdnames[fd]) {
			fprintf(stderr, "AddFdName(%d): inconsistency\n", fd);
			delete fdnames[fd];
		}
		fdnames[fd]= strsave(name);
	}
	if (gDebug && msg)
		fprintf(stderr, "%s(%d = \"%s\")\n", msg, fd, name);
	return fd;
}

void File::RemoveFdName(int fd, const char *msg)
{
	if (gDebug && msg)
		fprintf(stderr, "%s(%d = \"%s\")\n", msg, fd, fdnames[fd]);
	if (fd >= 0 && fd < 256) {
		if (fdnames[fd]) {
			delete fdnames[fd];
			fdnames[fd]= 0;
		} else {
			fprintf(stderr, "RemoveFdName(%d): inconsistency\n", fd);
		}
	}
}

const char *File::FdName(int fd)
{
	if (fd >= 0 && fd < 256)
		return fdnames[fd];
	return 0;
}

int File::Open(const char *name, int mode, const char *msg)
{
	if (msg == 0)
		msg= "File::Open";
	return AddFdName(::open(name, mode), name, msg);
}

int File::Creat(const char *name, int mode, const char *msg)
{
	if (msg == 0)
		msg= "File::Create";
	return AddFdName(::creat(name, mode), name, msg);
}

int File::Close(int fd, const char *msg)
{
	if (msg == 0)
		msg= "File::Close";
	RemoveFdName(fd, msg);
	return ::close(fd);
}

int File::Read(int fd, char *buf, int sz)
{
	int ec= ::read(fd, buf, sz);
	if (ec < 0) {
#ifdef EWOULDBLOCK
		if (errno == EWOULDBLOCK )
			return -2;
#endif
#ifdef EAGAIN
		if (errno == EAGAIN)
			return -2;
#endif
		//perror("File::Read");
		return -1;      // fatal error
	}
	return ec;  // ok or EOF
}

int File::Write(int fd, const char *buf, int sz)
{
	int ec= ::write(fd, buf, sz);
	if (ec < 0) {
#ifdef EWOULDBLOCK
		if (errno == EWOULDBLOCK )
			return -2;
#endif
#ifdef EAGAIN
		if (errno == EAGAIN)
			return -2;
#endif
		perror("File::Write");
		return -1;      // fatal error
	}
	return ec;
}

long File::Lseek(int fd, long off, int mode)
{
	return ::lseek(fd, off, mode);
}

int File::Unlink(const char *name)
{
	return ::unlink(name);
}

int File::Link(const char *from, const char *to)
{
	return ::link(from, to);
}

int File::SetNonBlock(int fd)
{
	return unix_nonblock(fd);
}

